//
//  PPNotificationKVObserver.h
//  PPMainLive
//
//  Created by edy on 2022/6/14.
//  Copyright © 2022 twksky. All rights reserved.
//

#import <Foundation/Foundation.h>

/*
 自动removeObserver的KVO和通知
 原理：会在内部创建一个对象作为KVO的观察者，挂在被观察者身上作为一个属性，如此被观察者释放时，会优先释放自身属性，属性上的KVO的观察者就触发了dealloc，如此就可以提前自动释放KVO的监听，开发者也不用去手动释放
 */

typedef void(^PPNotificationKVObserverChangeBlock)(id _Nullable object, NSDictionary<NSKeyValueChangeKey, id> * _Nullable change, NSString *_Nullable keyPath);

@interface PPNotificationKVObserver : NSObject
@end

@interface NSObject (PPNotificationKVObserver)
#pragma - mark KVO
/// KVO
/// @param keyPath 监听自己keyPath对应值的变化
/// @param options options
/// @param action 注意block内不要循环引用。action为nil的话，return nil。
- (void)pp_addObserverForKeyPath:(nonnull NSString *)keyPath options:(NSKeyValueObservingOptions)options changeAction:(nonnull PPNotificationKVObserverChangeBlock)action;

/// KVO
/// @param keyPaths 监听自己keyPaths对应值的变化
/// @param options options
/// @param action 注意block内不要循环引用。action为nil的话，return nil。
- (void)pp_addObserverForKeyPaths:(nonnull NSArray <NSString *>*)keyPaths options:(NSKeyValueObservingOptions)options changeAction:(nonnull PPNotificationKVObserverChangeBlock)action;

#pragma - mark Notification
/// 通知服务
/// @param aName 服务名
/// @param block 回调
- (void)pp_addObserverWithName:(nullable NSNotificationName)aName block:(void(^_Nullable)(NSNotification * _Nonnull notification))block;

/// 发出通知,与系统方法一致[[NSNotificationCenter defaultCenter] postNotificationName:aName object:anObject userInfo:aUserInfo]
/// @param aName 服务名
/// @param aUserInfo aUserInfo
- (void)pp_postNotificationName:(nullable NSNotificationName)aName userInfo:(nullable NSDictionary *)aUserInfo;

/// 发出通知,与系统方法一致[[NSNotificationCenter defaultCenter] postNotificationName:aName object:anObject userInfo:aUserInfo]
/// @param aName 服务名
/// @param anObject anObject
/// @param aUserInfo aUserInfo
- (void)pp_postNotificationName:(nullable NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;
/// 移除通知服务
/// @param aName 服务名
- (void)pp_removeObserverName:(nullable NSNotificationName)aName;
@end
